#include "shamrocket.hpp"
#include "../score/score.hpp"

#include <iostream>

ShamRocket::ShamRocket() {
		
}

ShamRocket::~ShamRocket() {
	
}

void ShamRocket::init(Engine *engine) {
	stars.SetImage(engine->getImage("data/shamrocket/stars.png"));
	stars.SetPosition(0.f, 0.f);
	scene.SetImage(engine->getImage("data/shamrocket/scene.png"));
	scene.SetPosition(0.f, 0.f);
	
	background = sf::Shape();
	background.AddPoint(sf::Vector2f(0.f, -1200.f), sf::Color(0, 0, 0, 255));
	background.AddPoint(sf::Vector2f(800.f, -1200.f), sf::Color(0, 0, 0, 255));
	background.AddPoint(sf::Vector2f(800.f, 600.f), sf::Color(14, 78, 123, 255));
	background.AddPoint(sf::Vector2f(0.f, 600.f), sf::Color(14, 78, 123, 255));
	
	int i = 0;
	for(std::map<int, Player>::iterator iPlayer = engine->players.begin(); iPlayer != engine->players.end(); iPlayer++) {
		int index = (*iPlayer).first;
		
		i++;
		sf::Sprite pad, rocket, reactor, gauge, gaugeCursor;
		rocket.SetImage(engine->getImage("data/shamrocket/rocket.png"));
		rocket.SetColor((*iPlayer).second.color);
		rocket.SetCenter(sf::Vector2f(rocket.GetImage()->GetWidth() / 2.f, rocket.GetImage()->GetHeight() / 2.f));
		rocket.SetPosition(sf::Vector2f(800.f * i / (engine->players.size() + 1), 512.f));
		float scale = sf::Randomizer::Random(0.9f, 1.1f);
		rocket.SetScale(scale, scale);
		
		pad.SetImage(engine->getImage("data/shamrocket/pad.png"));
		pad.SetCenter(sf::Vector2f(rocket.GetImage()->GetWidth() / 2.f, rocket.GetImage()->GetHeight() / 2.f));
		pad.SetScale(scale, scale);
		
		reactor.SetImage(engine->getImage("data/shamrocket/reactor.png"));
		reactor.SetSubRect(sf::IntRect(0, 0, 64, 64));
		reactor.SetScale(scale, scale);
		reactor.SetCenter(reactor.GetImage()->GetHeight() / 2.f, reactor.GetImage()->GetHeight() / 2.f);
		
		gauge.SetImage(engine->getImage("data/shamrocket/gauge.png"));
		gauge.SetCenter(gauge.GetImage()->GetWidth() / 2.f, gauge.GetImage()->GetHeight() / 2.f);
		gaugeCursor.SetImage(engine->getImage("data/shamrocket/gauge-cursor.png"));
		gaugeCursor.SetCenter(gaugeCursor.GetImage()->GetWidth() / 2.f, gaugeCursor.GetImage()->GetHeight());
		
		shammers[index].pad = pad;
		shammers[index].rocket = rocket;
		shammers[index].reactor = reactor;
		shammers[index].reactorTime = 0.f;
		shammers[index].reactorFrame = 0;
		shammers[index].gauge = gauge;
		shammers[index].gaugeCursor = gaugeCursor;
		
		shammers[index].score = sf::Randomizer::Random(0.f, 5000.f);
		shammers[index].scoreMove = sf::Randomizer::Random(0, 1);
		
		shammers[index].scale = scale;
		shammers[index].scaleSpeed = 0.f;
		shammers[index].won = false;
	}
	
	countdown = 5.f;
	countdownString.SetText(val2str(int(countdown)));
	countdownString.SetFont(engine->getFont("data/fonts/BELIEVER.TTF"));
	countdownString.SetColor(sf::Color(255, 255, 255, 255));
	countdownString.SetPosition(400.f - countdownString.GetRect().GetWidth(), 20.f);
	
	remaining = shammers.size();
	quitTime = 2.f;
	clock.Reset();
}

void ShamRocket::cleanup() {
	shammers.clear();
}

void ShamRocket::pause() {
	
}

void ShamRocket::resume() {
	clock.Reset();
}

void ShamRocket::processEvent(Engine *engine, PlayerEvent& event) {
	switch(event.type) {
		case PlayerEvent::Quit:
		{
			if(event.state)
				engine->changeState(Score::getSingleton());
			break;
		}
		case PlayerEvent::Action1:
			if(event.state) {
				if(countdown > 0.f)
					shammers[event.player].scoreMove = 2;
			}
			break;
		default:
			break;
	}
}

void ShamRocket::update(Engine *engine) {
	float time = clock.GetElapsedTime();
	clock.Reset();
	
	if(countdown > 0.f) {
		countdown -= time;
		if(countdown < 0.f) countdown = 0.f;
		countdownString.SetText(val2str(int(countdown)));
		countdownString.SetPosition(400.f - countdownString.GetRect().GetWidth(), 20.f);
	} else {
		background.Move(0.f, time * 300.f);
		scene.Move(0.f, time * 300.f);
		
	}
	
	if(remaining <= 1) {
		quitTime -= time;
		if(quitTime <= 0.f) engine->changeState(Score::getSingleton());
	}
	
	for(std::map<int, Shammer>::iterator iShammer = shammers.begin(); iShammer != shammers.end(); iShammer++) {
		int index = (*iShammer).first;
		Shammer& shammer = (*iShammer).second;
		
		if((engine->players[index].actions[PlayerEvent::MoveLeft].state) && (!engine->players[index].actions[PlayerEvent::MoveRight].state)) {
			shammer.rocketSpeed -= sf::Vector2f(400.f * time, 0.f);
			if(shammer.rocketSpeed.x < -400.f) shammer.rocketSpeed.x = -400.f;
		} else if((engine->players[index].actions[PlayerEvent::MoveRight].state) && (!engine->players[index].actions[PlayerEvent::MoveLeft].state))
			shammer.rocketSpeed += sf::Vector2f(400.f * time, 0.f);
		if(shammer.rocketSpeed.x > 400.f) shammer.rocketSpeed.x = 400.f;
		else {
			if(shammer.rocketSpeed.x < 0.f) {
				shammer.rocketSpeed.x += 100.f * time;
				if(shammer.rocketSpeed.x > 0.f) shammer.rocketSpeed.x = 0.f;
			} else if(shammer.rocketSpeed.x > 0.f) {
				shammer.rocketSpeed.x -= 100.f * time;
				if(shammer.rocketSpeed.x < 0.f) shammer.rocketSpeed.x = 0.f;
			}
		}
		
		shammer.rocket.Move(shammer.rocketSpeed * time);
		if(shammer.rocket.GetPosition().x < shammer.rocket.GetImage()->GetWidth() / 2.f) shammer.rocket.SetX(shammer.rocket.GetImage()->GetWidth() / 2.f);
		if(shammer.rocket.GetPosition().x > 800.f - shammer.rocket.GetImage()->GetWidth() / 2.f) shammer.rocket.SetX(800.f - shammer.rocket.GetImage()->GetWidth() / 2.f);
				
		if(countdown == 0.f) {
			shammer.reactorTime += time;
			while(shammer.reactorTime > 0.1f) {
				shammer.reactorTime -= 0.1f;
				shammer.reactorFrame++;
			}
			shammer.reactorFrame %= 4;
			shammer.reactor.SetSubRect(sf::IntRect(64 * shammer.reactorFrame, 0, 64 * (shammer.reactorFrame + 1), 64));
			
			shammer.pad.Move(0.f, time * 300.f);
			if(shammer.score > 0.f) {
				if(shammer.rocket.GetPosition().y > 512.f + (384.f * (remaining - (int)shammers.size()) / (float)shammers.size()))
					shammer.rocket.Move(0.f, ((512.f + (384.f * (remaining - (int)shammers.size()) / (float)shammers.size())) - shammer.rocket.GetPosition().y) * time);
				
				if(remaining > 1) {
					shammer.score -= time * 300.f;
					if(shammer.score < 0.f) {
						shammer.score = 0.f;
						remaining--;
					}
				} else if(shammer.won == false) {
					engine->players[index].score += 10;
					shammer.won = true;
				}
			} else {
				if(shammer.rocketSpeed.y < 400.f) {
					shammer.rocketSpeed.y += 300.f * time;
					if(shammer.rocketSpeed.y > 400.f)
						shammer.rocketSpeed.y = 400.f;
				}
			}
			
			if(shammer.rocket.GetScale().x < shammer.scale) {
				shammer.scaleSpeed += 0.2f * time;
				if(shammer.scaleSpeed > 0.3f) shammer.scaleSpeed = 0.3f;
				shammer.rocket.SetScale(shammer.rocket.GetScale().x + shammer.scaleSpeed * time, shammer.rocket.GetScale().x + shammer.scaleSpeed * time);
				
				if(shammer.rocket.GetScale().x >= shammer.scale)
					shammer.scale = sf::Randomizer::Random(0.8f, 1.25f);
			} else {
				shammer.scaleSpeed -= 0.2f * time;
				if(shammer.scaleSpeed < -0.3f) shammer.scaleSpeed = -0.3f;
				shammer.rocket.SetScale(shammer.rocket.GetScale().x + shammer.scaleSpeed * time, shammer.rocket.GetScale().x + shammer.scaleSpeed * time);
				
				if(shammer.rocket.GetScale().x >= shammer.scale)
					shammer.scale = sf::Randomizer::Random(0.8f, 1.25f);
			}

		} else {
			if(shammer.scoreMove == 0) {
				shammer.score += time * 20000.f;
				if(shammer.score >= 5000.f) {
					shammer.score = 5000.f - (shammer.score - 5000.f);
					shammer.scoreMove = 1;
				}
			} else if(shammer.scoreMove == 1) {
				shammer.score -= time * 20000.f;
				if(shammer.score <= 0.f) {
					shammer.score = -shammer.score;
					shammer.scoreMove = 0;
				}
			}
			
			shammer.gauge.SetPosition(shammer.rocket.GetPosition().x, 400);
			shammer.gaugeCursor.SetPosition(shammer.gauge.GetPosition() + sf::Vector2f(int(shammer.gauge.GetImage()->GetWidth()) / 2.f, 0.f) * (shammer.score - 2500.f) / 2500.f);
			
			shammer.pad.SetPosition(shammer.rocket.GetPosition() + sf::Vector2f(0.f, 112.f * shammer.rocket.GetScale().x));
		}
		
		shammer.reactor.SetPosition(shammer.rocket.GetPosition() + sf::Vector2f(0.f, 72.f * shammer.rocket.GetScale().x));
		shammer.reactor.SetScale(shammer.rocket.GetScale().x, shammer.rocket.GetScale().x);
		//shammer.scoreString.SetPosition(shammer.rocket.GetPosition() + sf::Vector2f(0.f, -64.f * shammer.rocket.GetScale().x));
	}
}

void ShamRocket::draw(Engine *engine) {
	engine->window.Draw(background);
	engine->window.Draw(stars);
	engine->window.Draw(scene);
	
	shammerZs.clear();
	for(std::map<int, Shammer>::iterator iShammer = shammers.begin(); iShammer != shammers.end(); iShammer++)
		shammerZs[(*iShammer).second.rocket.GetScale().x] = &(*iShammer).second;
	
	for(std::map<float, Shammer*>::iterator iShammerZ = shammerZs.begin(); iShammerZ != shammerZs.end(); iShammerZ++) {
		engine->window.Draw((*iShammerZ).second->pad);
		if((countdown == 0.f) && ((*iShammerZ).second->score > 0.f)) engine->window.Draw((*iShammerZ).second->reactor);
		engine->window.Draw((*iShammerZ).second->rocket);
		
		if((countdown > 0.f) && ((*iShammerZ).second->scoreMove != 2)) {
			engine->window.Draw((*iShammerZ).second->gauge);
			engine->window.Draw((*iShammerZ).second->gaugeCursor);
		}
	}
	
	if(countdown > 0.f) engine->window.Draw(countdownString);
}
